

import java.util.ArrayList;

/**
 * Abstract class representing a Neuron, hold the basic functions used by the neural network
 *
 */
public abstract class AbstractNeuron {
	
	public static final double LEARNING_RATE = 0.2;
	
	protected double value;
	protected double error;
	protected double entrySum;
	protected ArrayList<NeuralLink> inputList;
	protected ArrayList<NeuralLink> outputList;
	
	protected abstract double activationFunction(double e);
	protected abstract double activationFunctionDerivative(double e);
	
	public AbstractNeuron() {
		inputList = new ArrayList<NeuralLink>();
		outputList = new ArrayList<NeuralLink>();
	}
	
	public void correctError() {
		for (NeuralLink link : inputList) {
			// Compute the new weight using the error value
			link.setWeight(link.getWeight() + (LEARNING_RATE * error * activationFunctionDerivative(entrySum) * link.getSender().getValue()));
		}
	}
	
	public void computeValue() {
		entrySum = 0;
		for (NeuralLink link : inputList) {
			// apply weight
			double tempValue = link.getSender().getValue() * link.getWeight();
			// sum it
			entrySum += tempValue;
		}
		// Apply the activation function
		value = activationFunction(entrySum);
	}
	
	public void computeError() {
		double sum = 0;
		for (NeuralLink link : outputList) {
			// Compute the error from this link
			double linkError = link.getReceiver().getError() * link.getWeight();
			// sum it
			sum += linkError;
		}
		// set the error value of the node
		error = sum;
	}
	
	public double getError() {
		return error;
	}
	public double getValue() {
		return value;
	}
	
	public void addToInputList(NeuralLink link) {
		inputList.add(link);
	}
	
	public void addToOutputLink(NeuralLink link) {
		outputList.add(link);
	}
}
